import com.arcadedb.database.Database;
import com.arcadedb.database.DatabaseFactory;
import com.arcadedb.graph.MutableVertex;
import com.arcadedb.graph.Vertex;
import com.arcadedb.query.sql.executor.ResultSet;
import com.arcadedb.schema.Property;
import com.arcadedb.schema.Schema;
import com.arcadedb.schema.Type;
import com.arcadedb.schema.VertexType;
import indi.hjhk.csv.CSVReader;
import indi.hjhk.exception.ExceptionSerializer;
import indi.hjhk.log.Logger;
import nju.hjh.arcadedb.timeseries.DataType;
import nju.hjh.arcadedb.timeseries.TSUpdateStrategy;
import nju.hjh.arcadedb.timeseries.TimeseriesEngine;
import nju.hjh.arcadedb.timeseries.datapoint.DoubleDataPoint;
import nju.hjh.arcadedb.timeseries.datapoint.LongDataPoint;
import nju.hjh.arcadedb.timeseries.datapoint.StringDataPoint;
import nju.hjh.arcadedb.timeseries.exception.TimeseriesException;

import javax.xml.crypto.Data;
import java.io.IOException;

public class CsvInsertTest {
    public static void singleObjInsert() throws IOException {
        Logger logger = Logger.getPureLogger("CSV_Arcade");
        CSVReader reader = new CSVReader("/hdd/users/hjh/test.csv");

        try {
            reader.readHeader();
        }catch (CSVReader.CSVFormatException e){
            reader.close();
            return;
        }

        DatabaseFactory dbf = new DatabaseFactory("./databases/test");
        Database db;
        if (dbf.exists()){
            db = dbf.open();
        }else{
            db = dbf.create();
        }

        final int commitSize = 1000;

        long startTime = System.currentTimeMillis();

        Vertex test = ArcadeTSDBWorker.getOrNewVertexById(db, "test", "id", "test");

        TimeseriesEngine tsEngine = TimeseriesEngine.getInstance(db);

        int count = 0;
        tsEngine.begin();

        while (reader.next()){
            long timestamp = reader.getLong("time");
            String curStr = reader.getString("str");
            long curInt = reader.getLong("int");
            double curDouble = reader.getDouble("double");

            try {
                tsEngine.insertDataPoint(test, "str", DataType.STRING, new StringDataPoint(timestamp, curStr), TSUpdateStrategy.ERROR);
                tsEngine.insertDataPoint(test, "int", DataType.LONG, new LongDataPoint(timestamp, curInt), TSUpdateStrategy.ERROR);
                tsEngine.insertDataPoint(test, "double", DataType.DOUBLE, new DoubleDataPoint(timestamp, curDouble), TSUpdateStrategy.ERROR);
            }catch (TimeseriesException e){
                tsEngine.rollback();
                db.close();
                logger.logOnStderr(ExceptionSerializer.serializeAll(e));
                return;
            }

            count++;
            if (count >= commitSize){
                tsEngine.commit();
                //logger.logOnStdout("committed %d records", count);
                tsEngine.begin();
                count = 0;
            }
        }

        long elapsed = System.currentTimeMillis() - startTime;
        logger.logOnStdout("time used: %dms", elapsed);

        db.close();
        reader.close();
    }

    public static void multiObjInsert() throws IOException {
        Logger logger = Logger.getPureLogger("CSV_Arcade");
        CSVReader reader = new CSVReader("/hdd/users/hjh/test2.csv");

        try {
            reader.readHeader();
        }catch (CSVReader.CSVFormatException e){
            reader.close();
            return;
        }

        DatabaseFactory dbf = new DatabaseFactory("./databases/test");
        Database db;
        if (dbf.exists()){
            db = dbf.open();
        }else{
            db = dbf.create();
        }

//        final int commitSize = 1000;
        final int statSize = 100000;

        long startTime = System.currentTimeMillis();

        TimeseriesEngine tsEngine = TimeseriesEngine.getInstance(db);

//        int count = 0;
        int statCount = 0;
        tsEngine.begin();

        while (reader.next()){
            long timestamp = reader.getLong("time");
            String curObj = reader.getString("obj");
            long curInt = reader.getLong("int");
            double curDouble = reader.getDouble("double");

            Vertex object = ArcadeTSDBWorker.getOrNewVertexById(db, "test", "id", curObj);

            try {
                tsEngine.insertDataPoint(object, "int", DataType.LONG, new LongDataPoint(timestamp, curInt), TSUpdateStrategy.ERROR);
                tsEngine.insertDataPoint(object, "double", DataType.DOUBLE, new DoubleDataPoint(timestamp, curDouble), TSUpdateStrategy.ERROR);
            }catch (TimeseriesException e){
                tsEngine.rollback();
                db.close();
                logger.logOnStderr(ExceptionSerializer.serializeAll(e));
                return;
            }

            tsEngine.commit();
            tsEngine.begin();

            statCount++;
            if (statCount >= statSize) {
                logger.logOnStdout("committed %d records", statCount);
                statCount = 0;
            }

//            count++;
//            if (count >= commitSize){
//                tsEngine.commit();
//                //logger.logOnStdout("committed %d records", count);
//                tsEngine.begin();
//                statCount+=count;
//                if (statCount >= statSize){
//                    logger.logOnStdout("committed %d records", statCount);
//                    statCount = 0;
//                }
//                count = 0;
//            }
        }

        tsEngine.commit();
        long elapsed = System.currentTimeMillis() - startTime;
        logger.logOnStdout("time used: %dms", elapsed);

        db.close();
        reader.close();
    }

    public static void main(String[] args) throws IOException {
        multiObjInsert();
    }
}
